package edu.cicese.tm;

import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
import com.sun.java.swing.plaf.windows.WindowsBorders;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 23/03/11
 * Time: 09:53 AM
 */
public class FrameTagEdition extends JFrame{
	private FrameSpace frmSpace;
	private FrameTagEdition frmTagEdition;

	private JLabel lblTagPreview;
	private JTextArea taTagAnnotation;

	private String spaceID, tagID;
	private String annotation;
	public boolean /*newAudioClip, */newVideoClip, initialStateAnnotation, initialStateAudio, initialStateVideo,
			annotationChanged, audioChanged, videoChanged, dateChanged, initialStateEnabled;
	public String date, initialDate;
	public JCheckBox chbAnnotation, chbAudio, chbVideo;
	private JToggleButton tbnAvailability;

	public FrameTagEdition(FrameSpace frm) {
		frmSpace = frm;
		frmTagEdition = this;
		setIconImage(new ImageIcon(getClass().getClassLoader().getResource("icons/icon.png")).getImage());
		setTitle("Edición de etiqueta");
		setLayout(null);
		setSize(394, 383);
		setResizable(false);

        addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				closeWindow(false);
			}
		});
		initComponents();
	}

	//! Creates GUI components
	private void initComponents() {
		lblTagPreview = new JLabel("", JLabel.CENTER);
		lblTagPreview.setBounds(5, 5, 325, 240);

		JButton btnBack = new JButton();
		addButton(btnBack, 335, 5, 32, 32, "Regresar (sin guardar cambios)", "back", null, getContentPane());
		btnBack.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionBack();
			}
		});

		JButton btnSave = new JButton();
		addButton(btnSave, 335, 62, 32, 32, "Guardar cambios", "save", null, getContentPane());
		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionSave();
			}
		});

		JButton btnAudio = new JButton();
		addButton(btnAudio, 335, 99, 32, 32, "Editar clip de audio", "audio", null, getContentPane());
		btnAudio.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				openAudioDialog();
			}
		});

		JButton btnVideo = new JButton();
		addButton(btnVideo, 335, 136, 32, 32, "Editar clip de video", "video", null, getContentPane());
		btnVideo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

			}
		});

		JButton btnCalendar = new JButton();
		addButton(btnCalendar, 335, 173, 32, 32, "Especificar fecha y hora", "calendar", null, getContentPane());
		btnCalendar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				openCalendarDialog();
			}
		});

		tbnAvailability = new JToggleButton();
		tbnAvailability.setSelectedIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/disabled.png")));
		tbnAvailability.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/enabled.png")));
		tbnAvailability.setBounds(335, 210, 32, 32);
		tbnAvailability.setContentAreaFilled(false);
		tbnAvailability.setBorder(new EmptyBorder(0, 0, 0, 0));
		tbnAvailability.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				enableTag();
			}
		});
		getContentPane().add(tbnAvailability);

		chbAudio = new JCheckBox();
		SwingUtil.addCheckBox(chbAudio, 369, 105, 20, 20, null, getContentPane());
		chbVideo = new JCheckBox();
		SwingUtil.addCheckBox(chbVideo, 369, 142, 20, 20, null, getContentPane());
		chbAnnotation = new JCheckBox();
		SwingUtil.addCheckBox(chbAnnotation, 369, 290, 20, 20, null, getContentPane());

		taTagAnnotation = new JTextArea();
		taTagAnnotation.setFont(new Font("Segoe UI", Font.PLAIN, 13));
		taTagAnnotation.setLineWrap(true);
		taTagAnnotation.setForeground(Color.darkGray);

		JScrollPane spTagAnnotation = new JScrollPane(taTagAnnotation, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		spTagAnnotation.setBounds(5, 250, 360, 100);
		spTagAnnotation.setBorder(new WindowsBorders.DashedBorder(Color.LIGHT_GRAY, 1));

		getContentPane().add(lblTagPreview);
		getContentPane().add(spTagAnnotation);
	}

	//! Resets the components (loading the necessary information)
	private void setComponents() {
		String filename = Utilities.getTagDir(spaceID) + Utilities.tagSize + "\\" + tagID + "\\" + tagID;
		// Load tag image
		lblTagPreview.setIcon(new ImageIcon(SwingUtil.getScaledImage(new ImageIcon(filename + ".png").getImage(),
				325, 240)));
		// Load tag annotation
		annotation = new File(filename + ".txt").exists() ? Utilities.loadString(filename + ".txt") : "";
		annotation = annotation == null ? "" : annotation;
		System.out.println(annotation + "..." + filename);
		taTagAnnotation.setText(annotation);
		taTagAnnotation.setCaretPosition(0);
		taTagAnnotation.getDocument().addDocumentListener(new DocumentListener() {
			public void insertUpdate(DocumentEvent e) {
				annotationUpdated();
			}

			public void removeUpdate(DocumentEvent e) {
				annotationUpdated();
			}

			public void changedUpdate(DocumentEvent e) {
			}
		});
		chbAnnotation.setSelected(!annotation.equals(""));
		initialStateAnnotation = chbAnnotation.isSelected();
		// Check for audio clip
		chbAudio.setSelected(new File(filename + ".wav").exists());
		initialStateAudio = chbAudio.isSelected();
		// Check for video clip
		chbVideo.setSelected(new File(filename + ".3gp").exists());
		initialStateVideo = chbVideo.isSelected();
		// Load tag date
		JSONObject joDate = null;
		if (new File(filename + ".date").exists()) {
			date = initialDate = Utilities.loadString(filename + ".date");
			joDate = (JSONObject) JSONValue.parse(date);
		}
		if (joDate == null) {
			date = initialDate = "";
			joDate = new JSONObject();
		}

		// Check tag availability
//		JSONObject joDate = (JSONObject) JSONValue.parse(date);
		if (/*joDate != null && */joDate.get("enabled") != null) {
			initialStateEnabled = Boolean.valueOf(joDate.get("enabled").toString());
		}
		else {
			initialStateEnabled = true;
		}
		tbnAvailability.setSelected(!initialStateEnabled);
		enableTag();

		/*newAudioClip = */newVideoClip = false;
	}
	
	//! Sets the initial values
	public void setValues(String spaceID, String tagID) {
		this.spaceID = spaceID;
		this.tagID = tagID;
		setComponents();
	}

	//! Closes the window and brings back the spaceID window
	private void closeWindow(boolean saveOrBack) {
		if (saveOrBack) {
			setVisible(false);
		}
		frmSpace.setVisible(true);
		frmSpace.toFront();
	}

	//! Called when the Back button is clicked
	private void actionBack() {
		closeWindow(true);
	}

	//! Called when the Save button is clicked
	private void actionSave() {
		if (isTagModified()) {
			System.out.println("Modificada");
			saveTag();
		}
		// Close tag edition window
		closeWindow(true);
	}

	//! Saves the changes of the five kind of tags
	private void saveTag() {
		for (String tagSize : Utilities.tagSizes) {
			saveTag(tagSize);
		}
		// Delete temporal audio file
		Utilities.deleteDirectory(Utilities.spaceDir + "tmpAudio.wav");
		// Add entry to changelog
		modifyTagChangelog();
		// Update tag thumbnails
		frmSpace.setComponents();
	}

	//! Saves the tag information to the proper files
	@SuppressWarnings({"unchecked"})
	private void saveTag(String tagSize) {
		String tagDir = Utilities.getTagDir(spaceID) + tagSize + "\\" + tagID + "\\";
		// Save the tag annotation
		if (annotationChanged) {
			if (chbAnnotation.isSelected()) {
				Utilities.saveString(tagDir + tagID + ".txt", taTagAnnotation.getText().trim());
			}
			else {
				Utilities.deleteDirectory(tagDir + tagID + ".txt");
			}
		}

		// Save the tag audio clip
		if (audioChanged) {
			if (chbAudio.isSelected()) {
//				Utilities.saveAudioClip(tagDir + tagID + ".wav");
				Utilities.copyFile(Utilities.spaceDir + "tmpAudio.wav", tagDir + tagID + ".wav");
			}
			else {
				Utilities.deleteDirectory(tagDir + tagID + ".wav");
			}

		}

		if (videoChanged) {
			//TODO: Save VIDEO
		}

		// Save the tag date
		if (dateChanged) {
			JSONObject joDate = (JSONObject) JSONValue.parse(date);
			joDate.put("enabled", !tbnAvailability.isSelected());
			Utilities.saveString(tagDir + tagID + ".date", joDate.toJSONString());
		}
	}

	//! Adds a 'tag modified' entry to the changelog
	@SuppressWarnings({"unchecked"})
	private void modifyTagChangelog() {
//		JSONArray jaChangelog = (JSONArray) JSONValue.parse(Utilities.loadString(Utilities.spaceDir + "changelog.ans"));
		JSONArray jaChangelog = Utilities.loadJSONArray(Utilities.spaceDir + "changelog.ans");
		JSONObject joSpace = new JSONObject();
		JSONArray jaTags = new JSONArray();
		JSONObject joTag;
		boolean spaceFound = false;
		for (Object obj : jaChangelog) {
			joSpace = (JSONObject) obj;
			if (joSpace.get("spaceID").toString().equals(spaceID) &&
					Integer.parseInt(joSpace.get("action").toString()) != Utilities.DELETED) {
				spaceFound = true;
				break;
			}
		}
		if (!spaceFound) {
			joSpace = new JSONObject();
			joSpace.put("spaceID", spaceID);
			joSpace.put("action", Utilities.NO_ACTION);
			joTag = new JSONObject();
			joTag.put("tagID", tagID);
			joTag.put("action", Utilities.MODIFIED);
			jaTags.add(joTag);
			joSpace.put("tags", jaTags);
			jaChangelog.add(joSpace);
		}
		else {
			jaTags = (JSONArray) joSpace.get("tags");
			boolean tagFound = false;
			for (Object obj : jaTags) {
				joTag = (JSONObject) obj;
				if (joTag.get("tagID").toString().equals(tagID) &&
						Integer.parseInt(joTag.get("action").toString()) != Utilities.DELETED) {
					tagFound = true;
					break;
				}
			}
			if (!tagFound) {
				joTag = new JSONObject();
				joTag.put("tagID", tagID);
				joTag.put("action", Utilities.MODIFIED);
				jaTags.add(joTag);
//				joSpace.put("tags", jaTags);
//				jaChangelog.add(joSpace);
			}
		}
		// save to the changelog file used to update the server tag repository cache
		Utilities.addToLog(spaceID, tagID, "TAGchangelog.ans");
		// save to the changelog file used to update the client tag repository
		Utilities.saveString(Utilities.spaceDir + "changelog.ans", jaChangelog.toJSONString());
	}

	//! Opens the audio recording dialog
	private void openAudioDialog() {
		setEnabled(false);
		File audioFile;
		if (!DialogAudio.tmpAudioSaved) {
			audioFile = new File(Utilities.getTagDir(spaceID) + Utilities.tagSize + "\\" + tagID + "\\" + tagID + ".wav");
		}
		else {
			audioFile = new File(Utilities.spaceDir + "tmpAudio.wav");
		}
		new DialogAudio(frmTagEdition, audioFile);
	}

	//! Opens the calendar dialog
	private void openCalendarDialog() {
		setEnabled(false);
		new DialogNotificationType(frmTagEdition, date);
	}

	//! Adds a JButton
	private void addButton(JButton button, int x, int y, int width, int height,
	                              String toolTipText, String iconName, JPanel pane, Container container) {
		Icon icon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + ".png"));
		Icon rIcon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + "O.png"));
		Icon pIcon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + "P.png"));
		SwingUtil.addButton(button, x, y, width, height, toolTipText, icon, rIcon, pIcon, pane, container);
	}

	//!
	private void annotationUpdated() {
//		if (!taTagAnnotation.getText().trim().equals(""))
		chbAnnotation.setSelected(!taTagAnnotation.getText().equals(""));
	}

	//! Checks if the user has made changes to the tag information
	private boolean isTagModified() {
		boolean /*tagModified = false, */tagModifiedAux = false;
		annotationChanged = audioChanged = videoChanged = dateChanged = false;
		// Check if the user changed the tag annotation
		if (!annotation.equals(taTagAnnotation.getText().trim()) ||
				(initialStateAnnotation != chbAnnotation.isSelected())) {
//			tagModified = true;
			annotationChanged = true;
		}

		// Check if the user recorded a new audio clip (and selected to include it)
		if (initialStateAudio != chbAudio.isSelected()) {
			tagModifiedAux = !(chbAudio.isSelected() && !DialogAudio.tmpAudioSaved);
		}
		else if (DialogAudio.tmpAudioSaved && chbAudio.isSelected()) {
			tagModifiedAux = true;
		}
		if (tagModifiedAux) {
//			tagModified = true;
			audioChanged = true;
		}

		// Check if the user recorded a new video clip (and selected to include it)
		if (initialStateVideo != chbVideo.isSelected()) {
			tagModifiedAux = !(chbVideo.isSelected() && !newVideoClip);
		}
		else if (newVideoClip && chbVideo.isSelected()) {
			tagModifiedAux = true;
		}
		if (tagModifiedAux) {
			videoChanged = true;
//			tagModified = true;
		}
		
		// Check if the user changed the tag date
		if (!initialDate.equals(date) || initialStateEnabled == tbnAvailability.isSelected()) {
			dateChanged = true;
//			tagModified = true;
		}

//		return tagModified;
		return annotationChanged || audioChanged || videoChanged || dateChanged;
	}

	public void enableTag() {
		if (tbnAvailability.isSelected()) {
			tbnAvailability.setToolTipText("Habilitar");
		}
		else {
			tbnAvailability.setToolTipText("Deshabilitar");
		}
	}

	public static void main(String [] a) {
		try {
			UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
			UIManager.put("Panel.background", Color.WHITE);
			UIManager.put("ProgressBar.selectionBackground", Color.WHITE);
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		FrameTagEdition frm = new FrameTagEdition(null);
		frm.setValues("01", "027");
		frm.setVisible(true);
	}
}
